// 是否有window对象
const NO_WINDOW =  typeof window === 'undefined'
// 是否支持touch事件
const CAN_TOUCH = !NO_WINDOW && ('ontouchstart' in window || navigator.msMaxTouchPoints > 0)
const EVENTS =  CAN_TOUCH?['touchstart']:['click']

// 处理指令参数
function handleDirectiveArguments(argument) {
  const type = typeof argument 
  // not function || object
  if (type !== 'function' && type !== 'object') {
    throw new Error('the value binded must be a function or an object')
  }

  // 处理好的参数
  return {
    handler: type === 'function' ? argument : argument.handler,//处理函数
    middleware: argument.middleware || ((item) => item),//中间件
    events: argument.event || EVENTS,//绑定事件类型
    capture: !!argument.capture, //事件是否捕获
    activate: !(argument.activate === false), //绑定的事件是否激活
    includeIframe: !(argument.includeIframe === false) //事件触发是否包括iframe层
  }
}

function execHandler({event,handler,middleware}) {
  if (middleware(event)) {
    handler(event)
  }
}

function addOnEvent(value) {
  const {
    el,
    event,
    handler,
    middleware,
  } = value
  const path = event.path || (event.composedPath && event.composedPath())
  const isOutside = path ? path.indexof(el) < 0 : !el.contains(event.target)
  if (!isOutside) return
  execHandler({event,handler,middleware})
}

function addOnEventInIframe(value) {
  const {
    el,
    event,
    handler,
    middleware,
  } = value
  setTimeout(() => {
    const {activeElement} = document
    const isOutside = activeElement && activeElement.tagName === 'IFRAME' && !el.contains(activeElement)
    if (!isOutside) return 
    execHandler({event,handler,middleware})
  }, 0); 
}


// 指令传参：value function || object
function bind(el, { value }) {
  console.log(el)
  const {
    handler,
middleware,
events,
capture,
activate,
includeIframe
  } = handleDirectiveArguments(value)
  if (!activate) return
  
  el['v-outside-Click'] = events.map((event) => ({
      event: event,
      target: document.documentElement,
    handler: (event) => addOnEvent({ el, event, handler, middleware }),
    capture
  }))

  if (includeIframe) {
    const iframeEvent = {
      event: 'blur',
      target: window,
      handler: (event) => addOnEventInIframe({ el, event, handler, middleware }),
      capture
    }
    el['v-outside-Click'] = [...el['v-outside-Click'],iframeEvent]
  }
  el['v-outside-Click'].forEach(({event,target,handle}) => {
    setTimeout(() => {
      target.addEventListener(event,handle,capture)
    }, 0);
  })
}

function unbind(el) {
  const handles = el['v-outside-Click'] || []
  handles.forEach(({ event, target, handle,capture }) => {
    target.removeEventListener(event,handle,capture)
  })
  delete el['v-outside-Click']
}

function update(el, { value, oldValue }) {
  if (JSON.stringify(value) === JSON.stringify(oldValue)) {
    return
  }
  unbind(el)
  bind(el, { value })
}

const derective = {
  bind,
  unbind,
  update
}

export default typeof window === 'undefined'? {} : derective


